package com.xiaogang.ggfw.utils.common;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.util.StringUtils;

import javax.annotation.PreDestroy;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * @Description 用来处理阿里文件上传，支持返回公共读路径和私有分享路径
 * #阿里OSS的配置
 * aliOssEndpoint: https://oss-cn-beijing.aliyuncs.com
 * aliOssAccessKeyId: LTAI5t9Eoyk1Vm35gsYcALgh
 * aliOssAccessKeySecret: g1LUVVtz7fGwBgFmPMLQ1xQPly8pzH
 * @Author WangZhencheng
 * @Date 2022/1/19 10:27
 */
public class AliOssUtil {

    // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    private String endpoint = null;//"https://oss-cn-beijing.aliyuncs.com";
    // 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
    private String accessKeyId = null;// "LTAI5t9Eoyk1Vm35gsYcALgh";
    private String accessKeySecret = null;// "g1LUVVtz7fGwBgFmPMLQ1xQPly8pzH";

    //不提供bucket时和不提供过期时间时的默认值。
    //Bucket 命名规范：1)只能包括小写字母，数字和短横线（-）；2)必须以小写字母或者数字开头；3)长度必须在 3-63 字节之间。
    private String defaultBucketName = "test";
    //单位秒
    private Integer defaultExpireTime = 1000;

    private OSS ossClient = null;

    public AliOssUtil() {

    }

    public AliOssUtil(String endpoint, String accessKeyId, String accessKeySecret) {
        this.endpoint = endpoint;
        this.accessKeyId = accessKeyId;
        this.accessKeySecret = accessKeySecret;
    }

    public void setDefaultBucketName(String defaultBucketName) {
        this.defaultBucketName = defaultBucketName;
    }

    public void setDefaultExpireTime(Integer defaultExpireTime) {
        this.defaultExpireTime = defaultExpireTime;
    }

    public void init() {
        getClient();
    }

    public OSS getClient() {
        if (null != ossClient) {
            return ossClient;
        }
        try {
            // 创建OSSClient实例。
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ossClient;
    }

    @PreDestroy
    public void shutDown() {
        if (null != ossClient) {
            ossClient.shutdown();
        }
        ossClient = null;
    }

    /**
     * 上传字符串
     *
     * @param bucketName
     * @param objectName
     * @param data
     * @return 返回公共访问地址
     */
    public String uploadString(String bucketName, String objectName, String data) throws Exception {
        InputStream is = null;
        if (null != data) {
            is = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
        }
        return uploadInputStream(bucketName, objectName, is, true);
    }

    /**
     * 上传一个流,返回公共读的路径，如果是私有bucket，需要返回STS的私有路径时，则需要自己额外生成私有路径
     *
     * @param bucketName
     * @param objectName
     * @param is
     * @param closeInputStream
     * @return 返回一个公共读的url, 比如： https://docdock-dev.oss-cn-beijing.aliyuncs.com/hello.txt
     */
    public String uploadInputStream(String bucketName, String objectName, InputStream is, boolean closeInputStream) throws Exception {
        OSS ossClient = getClient();
        Exception ex = null;
        try {
            if (objectName.startsWith("/")) {
                objectName = objectName.substring(1);
            }
            bucketName = fixBucket(bucketName);
            ossClient.putObject(bucketName, objectName, is);
        } catch (Exception e) {
            ex = e;
        } finally {
            if (closeInputStream) {
                closeCloseable(is);
            }
        }
        if (ex != null) {
            throw ex;
        }
        return generatePublicUrl(bucketName, objectName);
    }

    private String fixBucket(String bucket) {
        return StringUtils.hasLength(bucket) ? bucket : defaultBucketName;
    }

    /**
     * 上传文件
     *
     * @param bucketName
     * @param objectName
     * @param file
     * @return
     */
    public String uploadFile(String bucketName, String objectName, File file) {
        OSS ossClient = getClient();
        try {
            bucketName = fixBucket(bucketName);
            ossClient.putObject(bucketName, objectName, file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return generatePublicUrl(bucketName, objectName);
    }

    /**
     * 生成一个临时访问的链接
     *
     * @param bucketName
     * @param objectName
     * @param expireTime 指定了过期时间
     * @return
     */
    public String generatePresignedUrl(String bucketName, String objectName, Date expireTime) {
        bucketName = fixBucket(bucketName);
        if (null == expireTime) {
            expireTime = new Date(System.currentTimeMillis() + this.defaultExpireTime * 1000);
        }
        OSS ossClient = getClient();
        if (objectName.startsWith("/")) {
            objectName = objectName.substring(1);
        }
        //String bucketName, String key, Date expiration
        URL url = ossClient.generatePresignedUrl(bucketName, objectName, expireTime);
        return url.toString();
    }

    /**
     * 拼接一个公共读的url
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public String generatePublicUrl(String bucketName, String objectName) {
        bucketName = fixBucket(bucketName);
        String endpointPrefix = endpoint.substring(0, endpoint.indexOf("://") + 3);
        String endpointSufix = endpoint.substring(endpoint.indexOf("://") + 3);
        if (!endpointSufix.endsWith("/")) {
            endpointSufix += "/";
        }
        if (objectName.startsWith("/")) {
            objectName = objectName.substring(1);
        }
        //"https://oss-cn-beijing.aliyuncs.com"
        //https://manon-test.oss-cn-beijing.aliyuncs.com/exampledir/exampleobject.txt
        // ?versionId=CAEQIxiBgID0zrnB8xciIGI4NDQ1NDljYjg1ODQ0NjM5OTBkOTg2MzgyMDdiODYz
        return endpointPrefix + bucketName + "." + endpointSufix + objectName;
    }

    /**
     * 删除文件!
     *
     * @param filePath
     * @return
     */
    public boolean deleteFile(String filePath) {
        OssUrlInfo info = parseUrlInfo(filePath);
        boolean exist = ossClient.doesObjectExist(info.bucket, info.filePath);
        if (!exist) {
            return false;
        }
        ossClient.deleteObject(info.bucket, info.filePath);
        return true;
    }

    /**
     * 从一个url中获取对应的bucket 和path
     * /exampledir/exampleobject.txt=> bucket: defaultBucket, path:/exampledir/exampleobject.txt
     * https://manon-test.oss-cn-beijing.aliyuncs.com/exampledir/exampleobject.txt?versionId=CAEQIxiBgID0zrnB8xciIGI4NDQ1NDljYjg1ODQ0NjM5OTBkOTg2MzgyMDdiODYz
     * =>  bucket: manon-test, path:/exampledir/exampleobject.txt
     *
     * @param filePath
     * @return
     */
    public OssUrlInfo parseUrlInfo(String filePath) {
        OssUrlInfo rs = new OssUrlInfo();
        rs.raw = filePath;
        if (filePath.contains("://")) {
            String url = filePath;
            if (url.contains("?")) {
                url = url.substring(0, url.indexOf("?"));
            }
            if (url.contains("://")) {
                url = url.substring(url.indexOf("://") + 3);
            }
            //manon-test.oss-cn-beijing.aliyuncs.com/exampledir/exampleobject.txt
            rs.bucket = url.substring(0, url.indexOf("."));
            rs.filePath = url.substring(url.indexOf("/") + 1);
        } else {
            rs.bucket = defaultBucketName;
            rs.filePath = filePath;
        }
        if (rs.filePath.startsWith("/")) {
            rs.filePath = rs.filePath.substring(1);
        }
        return rs;
    }


    private void closeCloseable(Closeable closeable) {
        if (null != closeable) {
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 路径信息
     */
    public static class OssUrlInfo {
        /**
         * 原路径
         */
        public String raw;
        /**
         * bucket
         */
        public String bucket;
        /**
         * oss子路径 相对路径，不是以 / 开头的路径
         */
        public String filePath;
    }

    public static void main(String[] args) {

        //文件目录查看：https://oss.console.aliyun.com/bucket/oss-cn-beijing/manon-test/object?path=exampledir%2F

        // 填写Bucket名称，例如examplebucket。
        String bucketName = "manon-test";
// 填写文件名。文件名包含路径，不包含Bucket名称。例如exampledir/exampleobject.txt。
        String objectName = "exampledir/hello.png";

        AliOssUtil util = new AliOssUtil();

        String url = util.uploadFile(bucketName, objectName, new File("D:\\Wzc_Work\\ddl\\tmp\\hello.png"));

        System.out.println("上传公共路径是:" + url);

        //https://manon-test.oss-cn-beijing.aliyuncs.com/exampledir/hello.png?Expires=1642578224&OSSAccessKeyId=LTAI5t9Eoyk1Vm35gsYcALgh&Signature=ycLZOFRQoTo22BlIcWhxGPgAZSk%3D
        //https://manon-test.oss-cn-beijing.aliyuncs.com/exampledir/hello.png
        Date date = new Date(System.currentTimeMillis() + 900 * 1000);
        System.out.println("临时路径:" + util.generatePresignedUrl(bucketName, objectName, date));
        util.shutDown();

        //new ByteArrayInputStream(content.getBytes())

    }
}
